<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
Design by Free CSS Templates
http://www.freecsstemplates.org
Released for free under a Creative Commons Attribution 2.5 License
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>CSC560 Design and Analysis of Real-Time Systems</title>
<meta name="keywords" content="" />
<meta name="description" content="" />
<link href="../default.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="wrapper">
	<div id="header">
		<h1>CSC560</h1>
		<h2>Design and Analysis of Real-Time Systems</h2>
		<ul>
			<li class="first">
				<a href="../index.html" accesskey="1" title="">Home</a>
			</li>
			<li>
				<a href="index.html" accesskey="2" title=""><b>Project 1</b></a>
			</li>
			<li>
				<a href="../project2/index.html" accesskey="3" title="">Project 2</a>
			</li>
			<li>
				<a href="../project3/index.html" accesskey="4" title="">Project 3</a>
			</li>
			<li>
				<a href="../project4/index.html" accesskey="4" title="">Project 4</a>
			</li>
			<li>
				<a href="../project5/index.html" accesskey="4" title="">Project 5</a>
			</li>
		</ul>
	</div>
</div>

<div id="content">
	<div id="colOne">
		<h2>Development Process</h2>
		<p>
			In implementing the first project, various challenges were encountered. This section describes our development process, challenges encountered, and the respective solutions.		
		</p>
		<h2>Joystick</h2>
		<p>
			The first challenge to us was to catch and distinguish among the five joystick positions, namely, Select, Left, Right, Up, and Down, as the joystick would be used to remotely control the Roomba. In total there are five pins on port B and port E used to signal each joystick position. The relationship between each pin and its corresponding position is as shown in the Joystick Schematic.
			[Extracted from the AT90USBKey User Guide]
		</p>
		<p>
			<IMG SRC="../images/joystick-schematic.jpg" ALT="[Joystick Schematic]">
		</p>
		<p>
			Based on the Schematic and by referencing a previous project, Leader and Follower, we were able to catch each joystick position. We confirmed it by turning on a different on-board LED (There are two LEDs on board, each of which with two colors, green & red, hard-wired to pins[4..7] of port D.) for each joystick position. In addition, we managed to distinguish, for each position, whether the joystick was pressed once and released or was pressed and held in position. This latter was necessary in our design because it would be interpreted as a command to accelerate the remote Roomba.	
		</p>
		<p>
			The next challenge we encountered was whether to poll joystick actions or to use interrupt service routine (ISR).  One disadvantage of polling is the waste of CPU power when the joystick is idling. Nevertheless, we decided to use polling because of its simplicity and to avoid race condition and reentrancy of interrupt. 	
		</p>
		<p>
			In polling joystick actions, we discovered that the frequency of polling drastically affected the responsiveness of our system. Higher polling frequency resulted in firing too many joystick actions while lower polling frequency resulted in firing too few joystick actions. We fine tuned the polling frequency by changing the length of system delay through various experiments. 	
		</p>

		<h2>UART</h2>
		<p>
			Another requirement of the project is to calculate and display the speed of Roomba on a display screen. For this purpose and aiding in debugging, we used a separate UART chip as the interface between the primary AT90USBKey Controller and a dumb terminal for display. UART is the ideal choice as most modern computers today do not have serial communication ports but do have multiple USB ports. UART hence serves as a serial to USB interface. Note that in wiring the UART chip and the Controller, one must cross-wire the RXD1 and TXD1 of the Controller to the Tx and Rx of UART.	
		</p>
		<p>
			Our first discovery of UART was that both the UART chip and the dummy display terminal had to be configured at the same baud rate for successful communication. For that purpose, both were configured at 38400 bps as suggested by the TA, Neil. At first  we were able to print characters on the display successfully with TeraTerm 3.x running on the Windows XP desktop machine. However, it failed when later on we switched the display to our laptop running Windows Vista. This was subsequently resolved by installing TeraTerm 4.16 on Windows Vista.
		</p>

		<h2>nRF24L01 2.4 GHz Wireless Radio Chip</h2>
		<p>
			For this project, the nRF24L01 2.4 GHz wireless chip with Serial Peripheral Interface (SPI) is used for the wireless link and Neil has provided with us the radio driver and firmware for AT90UUSBKey to communicate with the nRF24L01 radio chip.
		</p>		
		<p>
			The following is the block diagram for nRF24L01. [Extracted from nRF24L01Single Chip 2.4GHz Transceiver Product Specification]
		</p>
		<p>
			<IMG SRC="../images/BlockDiagram-nRF24L01.jpg" ALT="[Block Diagram nRF24L01]">
		</p>
		<p>
			Because multiple controllers may communicate with the base station, each controller must assign a unique address to its radio. Each address took five bytes and ours was configured to be 0x1212121212. Initially we followed the wiring of the Roomba base station and connected PB5 to CSN of the radio chip. “The CSN (chip select not) pin is active-low, and is normally kept high. When this pin goes low, the 24L01 begins listening on its SPI port for data and processes it accordingly.” This worked well until we started to incorporate joystick actions and was unable to detect the Select action. We then realized that PB5 was hard-wired to joystick Select and hence the detection failure. This issue was consequently resolved by connecting CSN to any vacant pin and by modifying the source code of provided radio driver accordingly. (We chose PE6 as the vacant pin as shown in the schematics of our design.)
		</p>
			Another issue we encountered in using the radio chip was that at times the wireless link would freeze and no packets could be transmitted while the controller continued to accept joystick input. At first we tried to resolve it by alternating between two parameter values when invoking Radio_Transmit(). One was RADIO_WAIT_FOR_TX (blocking until packet transmitted) and the other was RADIO_RETURN_ON_TX (no blocking on packet transmission.) Still, the packet transmission would freeze at times. Eventually, we concluded that FIFOs were filled up at some point, perhaps because interference causing high drop rate of packet transmission or there were multiple controllers sending packets to the base station simultaneously.
		</p>
		<p>
			Therefore, we had to cut the power source to our radio chip by unplugging the USB cable to manually flush the FIFOs in order to resume packet transmission. Another solution was to instruct the radio to flush its FIFOs through the firmware when transmission failed on maximum retries. However, the latter would require modification of the “radio.h” provided by Neil.
		</p>
		
		<h2>Driving Roomba with the Joystick & SCI commands</h2>
		<p>
			As it’s required to use the joystick to remotely control the Roomba, we’ve defined a corresponding SCI instruction for each joystick position as follows:
			<ul>
				<li>Up: Go straight at 200 mm/s</li>
				<li>Down: Reverse at 100 mm/s</li>
				<li>Left: Rotate counterclockwise (CCW)</li>
				<li>Right: Rotate clockwise (CW)</li>
				<li>Select: Stop!</li>
				<li>Holding up: Go straight at 500 mm/s</li>
				<li>Holding down: Reverse straight at 300 mm/s</li>
				<li>Two consecutive Up: Go straight at 500 mm/s</li>
				<li>Two consecutive Down: Reverse straight at 300 mm/s</li>
			</ul>
		</p>
		<p>
			The only SCI command opcode needed is Drive (opcode 137) to control Roomba’s wheel motion and to fulfill the project requirement. “The Drive command takes four data bytes, which are interpreted as two 16 bit signed values using twos-complement. The first two bytes specify the average velocity of the drive wheels in millimeters per second (mm/s), with the high byte sent first. The next two bytes specify the radius, in millimeters, at which Roomba should turn. The longer radii make Roomba drive straighter; shorter radii make it turn more. A Drive command with a positive velocity and a positive radius will make Roomba drive forward while turning toward the left. A negative radius will make it turn toward the right. Special cases for the radius make Roomba turn in place or drive straight.” [iRobot Roomba  Serial Command Interface (SCI) Specification] Since we’ve defined acceptable Roomba actions as above, the radius parameter is not needed in our design. 
		</p>
		<p>
			One challenge we experienced was in transmitting packets from the primary Controller to the remote Roomba station to control it with SCI commands. First we noticed that Roomba would not move and no status packets were returned as acknowledgement at times. The SCI command packets were sent out from the primary Controller as intended the Roomba did move as commanded from time to time. Apparently it was due to the incorrect mode of the Roomba. In fact, we discovered that Roomba must be in CONTROL mode in order to accept SCI command from the primary Controller. 
		</p>
		<p>
			To set Roomba in CONTROL mode, one must do the following: 
			<ul>
				<li>Lift the Roomba off the ground.</li>
				<li>Press the ‘Power’ button to turn it off.</li>
				<li>Press the “Power’ button to turn it back on.</li>
				<li>Press the ‘HWD’ (Hardware Reset) of the Roomba AT90USBKey controller.</li>
			</ul>
		</p>
		<p>
			Once Roomba was in CONTROL mode, we were able to command it accordingly with SPI commands. Note that since Roomba is not designed to process more than few commands per second and would otherwise become unpredictable, we’ve decided to engage 150-ms delay (through trial and error) in polling joystick action. 
		</p>
		
		<p>
			Driving Roomba straight forward and in reverse were accomplished by assigning special value to the radius in accordance with the SCI commands. Specifically,
				<li>Straight: radius = ox8000, with velocity between 0 and 500 ms</li>
				<li>Reverse: radius = ox8000, with velocity between 0 and -500 ms</li>
				<li>Turn in place counter-clockwise: radius = 1, with 0 velocity</li>
				<li>Turn in place clockwise: radius = -1, with 0 velocity</li>
		</p>
		<p>
			The challenge to us here was how to encode a negative hexadecimal value in 16 bits. For example, we needed to assign -1 to the radius to command the Roomba to rotate clockwise. Eventually, we figured out that to obtain -1 all we had to do was to count backward from 0. Hence, -1 was encoded as 0xffff. Similarly, velocity of -200 mm/s was encoded as 0xff38 (0xff00 == -256, 0x0038 == 56, and -200 == -256 +  56)		
		</p>
		<h2>Timer</h2>
		<p>
			In fulfilling the last requirement of the project, i.e. calculating the speed of the Roomba from the status packet returned, we used the timer library provided by Neil that utilized the AT90USBKey onboard TCNT 16-bit timer/counter. The elapsed time was calculated using Timer_Now() function and the distance traveled were obtained from the status packets received from Roomba. The Timer_Now() returns the number of ticks elapsed since the last initialization of the timer. Note that if “interrupts are disabled for more than 2 ms, then the tick counter will not be incremented and the timer results will be wrong.” Also, this value will rolls over every 65,536 ms.
		</p>
		<p>
			Speeds were then calculated with the ratio of distance traveled and time elapsed for several experiments. At first we were unable to get the right speed calculated but we found that the speeds calculated were consistently and roughly 6 times faster than the speed at which we set the Roomba to run (at 100 ms per second with SCI commands.)  We concluded that the Timer_Now() actually returns in roughly 30-ms ticks rather than 5-ms ticks as documented. This was confirmed subsequently by Neil and the Timer_Now() has been modified accordingly so that each tick was equal to 5 ms. 
		</p>
		<p>
			Because speed was calculated from the division of distance traveled by elapsed time, and both were of type integer, division operation resulted in loss of information. In fact, speed calculated was 0 most of time as the ratio of distance/(elapsed time) was less than 1. To work around it, we had to code it as speed = ((float) distance / time) * 1000. In addition, we learned that passing a floating point number to snprintf() for output would result in meaningless character (“?” character to be exact) to be printed. To resolve it, we then cast the calculated speed to int before printing it with snprintf(). 
		</p>
		<p>
			Another interesting observation was that speed calculated was not equal to the speed at which we instructed the Roomba to run. We concluded that the delay of SPI FIFO queues, the stand by time to switch between Rx and Tx mode, minimum pulse on CE to begin transmission, and perhaps the mechanical characteristics of the Roomba wheel motor all contributed to this discrepancy.
		</p>
	</div>
		
	<div id="colTwo">
		<h3>Project Sections</h3>
		<ul>
			<li class="first"><a href="hardware.html"><b>Hardware Description</b></a></li>
			<li><a href="design.html">Software Design</a></li>
			<li><a href="development_process">Development Process</a></li>
			<li><a href="../doxygen/html/index.html">Doxygen</a></li>
			<li><a href="tutorial.html">Tutorial</a></li>
			<li><a href="http://code.google.com/p/wireless-roomba">Google Code</a></li>
		</ul>
	</div>
</div>

<div id="footer">
	<p>@ 2009. All Rights Reserved. Design by <a href="http://www.freecsstemplates.org/">Free CSS Templates</a>.</p>
</div>

</body>
</html>
